package us.icitap.timsportal.ejb;

import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceException;
import javax.persistence.TransactionRequiredException;

import us.icitap.timsportal.business.SimpleUser;
import us.icitap.timsportal.ejb.remote.PortalBeanRemote;
import us.icitap.timsportal.entity.Module;
import us.icitap.timsportal.entity.Officer;
import us.icitap.timsportal.entity.OrgStructure;
import us.icitap.timsportal.entity.PortalSession;
import us.icitap.timsportal.entity.Role;
import us.icitap.timsportal.entity.User;
import us.icitap.timsportal.ws.util.RmisOSThread;
import us.icitap.timsportal.ws.util.RmisOfficerThread;

@Stateless(mappedName="PortalBean")
public class PortalBean implements PortalBeanLocal, PortalBeanRemote {

	@PersistenceContext
	private EntityManager em;
	
	public PortalBean(){}

	
	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public void foo() {
		// TODO Auto-generated method stub
		
	}
	
	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public Date getSysdate(){
		String sql = "SELECT SYSDATE FROM DUAL";
		return (Date) em.createNativeQuery(sql).getSingleResult();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<OrgStructure> getListOrgStructure(){
		try {
			return em.createQuery("select os from OrgStructure os")
			.getResultList();
		} catch (IllegalArgumentException e) {
			System.out.println("PortalBean.getListOrgStructure() "+e.getMessage());
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Module> getListModule(boolean all) {
		String str = "select m from Module m";
		if(!all)
			str+=" "+"where m.status = 1";
		try {
			return em.createQuery(str).getResultList();
		} catch (IllegalArgumentException e) {
			System.out.println("PortalBean.getListModule():"+ e.getMessage());
			return null;
		}
	}
	
	@Override
	public Role getRole(String id){
		return em.find(Role.class, id);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<User> getUserByRole(String roleId) {
		Role r = em.find(Role.class, roleId);
		return em.createQuery("select u from User u where ?1 MEMBER OF u.roles")
		.setParameter(1, r)
		.getResultList();
	}
	
	@Override
	public User getUserEntity(String username) {
		
		try {
			@SuppressWarnings("unchecked")
			List<User> results = em
					.createQuery("select u from User u where UPPER(u.username) = :username")
					.setParameter("username", username)
					.getResultList();
			User foundEntity = null;
			if (!results.isEmpty()) {
				// ignores multiple results
				foundEntity = results.get(0);
			}
			return foundEntity;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	@Override
	public User getUserLastUpdatedDettails(String username){
		try {
			@SuppressWarnings("unchecked")
			List<User> results = em
					.createQuery("select u from User u where UPPER(u.username) = :username")
					.setParameter("username", username)
					.getResultList();
			User foundEntity = null;
			if (!results.isEmpty()) {
				// ignores multiple results
				foundEntity = results.get(0);
			}
			if(foundEntity != null){
				if(foundEntity.getOfficer() != null){
					Officer officer = getRmisOfficerById(foundEntity.getOfficer().getOfficerId());
					foundEntity.setOfficer(officer);
				}
			}			
			return foundEntity;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	@Override
	public Officer getRmisOfficerById(String officerId){		
		RmisOfficerThread rmisOfficerThread = null;
		try {
			rmisOfficerThread = new RmisOfficerThread(officerId);
			rmisOfficerThread.start();
		} catch(SecurityException se){
			System.out.println("checkAcces throw SecurityException");
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("*RMIS-WS NUK PERGJIGJET*");
			e.printStackTrace();
		}
		try {
			Thread.sleep(1500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		return rmisOfficerThread.getOfficer();
	}
	
	@Override
	public List<Officer> getRmisOfficerByName(String name, String surname){
		RmisOfficerThread rmisOfficerThread = new RmisOfficerThread(name, surname);
		try {
			rmisOfficerThread.start();
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("*RMIS-WS NUK PERGJIGJET*");
			e.printStackTrace();
		}
		try {
			Thread.sleep(1500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		return rmisOfficerThread.getList();
	}
	
	@Override
	public List<OrgStructure> getRmisOrgStructureList(String arg){
		if(arg==null || arg=="")return null;
		Integer id = null;
		boolean isInt = false;
		try {
			id = Integer.parseInt(arg);
			isInt = true;
		} catch (NumberFormatException e) {
			isInt = false;
		}
		RmisOSThread rot = null;
		try{
			if(isInt)
			rot = new RmisOSThread(id);
			else rot = new RmisOSThread(arg);
			rot.start();
			Thread.sleep(1500);
		}catch(SecurityException se){
			System.out.println("checkAcces throw SecurityException");
		}catch(InterruptedException ie){
			
		}catch(Exception e){
			System.out.println("*RMIS-WS NUK PERGJIGJET*");
			e.printStackTrace();
		}
		return rot.getList();
	}
	
	@Override
	public Officer getDBOfficerById(String id){
		try {
			@SuppressWarnings("unchecked")
			List<Officer> list = em.createQuery("select o from Officer o where o.officerId = ?1 order by o.id DESC").setParameter(1, id).getResultList();
			Officer officer = null;
			if(!list.isEmpty())
				officer = list.get(0);
			return officer;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	

	@Override
	public User saveUser(User user) {
		return em.merge(user);
	}

	@Override
	public void savePortalSession(PortalSession portalSession) {
		try {
			em.merge(portalSession);
		} catch (Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
		}		
	}
	
	@Override
	public PortalSession searchPortalSessionInDB(String username, String portalSessionId , String moduleSessionId){	
		System.out.println("server");
		try {
			@SuppressWarnings("unchecked")
			List<PortalSession> results = em
					.createQuery("select p from PortalSession p where p.username = ?1 and p.portalSessionId = ?2 and p.moduleSessionId = ?3")
					.setParameter(1, username)
					.setParameter(2, portalSessionId)
					.setParameter(3, moduleSessionId)
					.getResultList();
			PortalSession foundEntity = null;
			if (!results.isEmpty()) {
				// ignores multiple results
				em.refresh(results.get(0));
				foundEntity = results.get(0);
			}
//			em.refresh(foundEntity);
			return foundEntity;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	@Override
	public PortalSession searchPortalSessionInDB(String portalSessionId , String moduleSessionId){		
		try {
			@SuppressWarnings("unchecked")
			List<PortalSession> results = em
					.createQuery("select p from PortalSession p where p.portalSessionId = ?1 and p.moduleSessionId = ?2")
					.setParameter(1, portalSessionId)
					.setParameter(2, moduleSessionId)
					.getResultList();
			PortalSession foundEntity = null;
			if (!results.isEmpty()) {
				// ignores multiple results
				em.refresh(results.get(0));
				foundEntity = results.get(0);
			}
			return foundEntity;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	@Override
	public PortalSession searchPortalSessionInDB(String portalSessionId){		
		try {
			@SuppressWarnings("unchecked")
			List<PortalSession> results = em
					.createQuery("select p from PortalSession p where p.portalSessionId = ?1")
					.setParameter(1, portalSessionId)
					.getResultList();
			PortalSession foundEntity = null;
			if (!results.isEmpty()) {
				// ignores multiple results
				em.refresh(results.get(0));
				foundEntity = results.get(0);
			}
			return foundEntity;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public SimpleUser getModuleUser(String portalSessionId, String moduleSessionId) {
		PortalSession portalSession = null;
		
		String sql = "select * from timsportal.PORTAL_SESSION t " +
		"where (sysdate - 1/(24)) <= t.module_entry_time " +
		"and t.portal_session_id = '" + portalSessionId + "'";
		System.out.println("PortalBean.getModuleUser()");
		
		try {
			List<PortalSession> results = em.createNativeQuery(sql, PortalSession.class).getResultList();
			if (!results.isEmpty())
				portalSession = results.get(0);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		System.out.println("PortalBean.getModuleUser()");
		if(portalSession==null)
			return null;
		String username = portalSession.getUsername();
		Module module = portalSession.getModule();
		
		portalSession.setModuleSessionId(moduleSessionId);
		portalSession.setModuleEntrySuccess(true);
		savePortalSession(portalSession);
		
		User user = getUserEntity(username);
		SimpleUser simpleUser = new SimpleUser(user);
		simpleUser.retainModuleRoles(module);
		String[] officerOSList = user.getOfficer().getParentStructureIds();
		simpleUser.retainModuleStructure(officerOSList, module);
		System.err.println(simpleUser);
		return simpleUser;	
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public String getModuleUsername(String portalSessionId, String moduleSessionId){
		PortalSession portalSession = null;
		
		String sql = "select * from timsportal.PORTAL_SESSION t " +
		"where (sysdate - 1/(24)) <= t.module_entry_time " +
		"and t.portal_session_id = '" + portalSessionId + "'";
		
		try {
			@SuppressWarnings("unchecked")
			List<PortalSession> results = em.createNativeQuery(sql, PortalSession.class).getResultList();
			if (!results.isEmpty()) {
				// ignores multiple results
//				em.refresh(results.get(0));
				portalSession = results.get(0);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
		if(portalSession==null)
			return null;
		
		portalSession.setModuleSessionId(moduleSessionId);
		savePortalSession(portalSession);

		return portalSession.getUsername();	
	}
	
	@Override
	public OrgStructure getOfficerBaseStructureByModule(Officer o, int moduleId){
//		Officer o = em.find(Officer.class, officerId);
		Module m = em.find(Module.class, moduleId);
//		System.err.println("*****"+m.getModuleName());
		if(o==null || m==null)return null;
		OrgStructure baseOs = null;
		loop:
			for(String id: o.getParentStructureIds()){
				try{
					Integer osId = Integer.parseInt(id.trim());
					for(OrgStructure os: m.getOrgStructures()){
//						System.err.print(os.getId()+"--");
//						System.err.println(osId+"-"+os.getId()+"  "+(osId==os.getId()));
						if(osId.equals(os.getId())){
							baseOs = os;break loop;
						}
					}
				}catch(NumberFormatException e){
					System.err.println(id+"  "+e.getMessage());
				}
			}		
		return baseOs;
	}


	@Override
	public Module saveModule(Module m, Collection<Role> rCol,
			Collection<OrgStructure> osCol) {
		if(m==null)
			return null;
//		if(rCol!=null && !rCol.isEmpty()){
//			m.getRoles().clear();
//			Set<Role> rTempSet = new HashSet<Role>();
//			rTempSet.addAll(rCol);
//			m.setRoles(rTempSet);
//		}
		
		if(osCol!=null && !osCol.isEmpty()){
			Set<OrgStructure> osTempSet = new HashSet<OrgStructure>();
			osTempSet.addAll(osCol);
			m.setOrgStructures(osTempSet);			
		}
		
		try {
			m = em.merge(m);
			em.flush();
		} catch (IllegalArgumentException e) {
			System.err.println("PortalBean.saveModule() "+e.getMessage());
			return null;
		} catch (TransactionRequiredException tre){
			System.err.println("PortalBean.saveModule() "+tre.getMessage());
			return null;
		} catch (PersistenceException pe){
			System.err.println("PortalBean.saveModule() "+pe.getMessage());
			return null;
		}
		
		return m;
	}

}
